using System;	
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace WebServer
{
	public class WebServer
	{
		
		private string sMyWebServerRoot ;
		private Socket mySocket;
 		 
		public WebServer(Socket s, string Location)
		{ 
			mySocket= s;
			sMyWebServerRoot = Location + "\\";
		}
        
		private string GetMimeType(string fileName)
		{
			if(fileName.EndsWith(".htm") || fileName.EndsWith(".html"))
				return "text/html";
			else if(fileName.EndsWith(".jpg") || fileName.EndsWith(".jpeg"))
				return "image/jpeg";
			else if(fileName.EndsWith(".gif"))
				return "image/gif";
			else if(fileName.EndsWith(".txt"))
				return "text/plain";
			else
				return "application/octet-stream";
		}
 		 
		private void SendHeader(string sHttpVersion, string sMIMEHeader, int iTotBytes, string sStatusCode)
		{
			String sBuffer = "";
			
			// if Mime type is not provided set default to text/html
			if (sMIMEHeader.Length == 0 ) sMIMEHeader = "text/html";  // Default Mime Type is text/html
			
			sBuffer = sBuffer + sHttpVersion + sStatusCode + "\r\n";
			sBuffer = sBuffer + "Server: MyWebServer-b\r\n";
			sBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "\r\n";
			sBuffer = sBuffer + "Accept-Ranges: bytes\r\n";
			sBuffer = sBuffer + "Content-Length: " + iTotBytes + "\r\n\r\n";
			Byte[] bSendData = Encoding.ASCII.GetBytes(sBuffer); 
			SendToBrowser(bSendData);
		
		}
 
		private void SendToBrowser(String sData)
		{ SendToBrowser (Encoding.ASCII.GetBytes(sData)); 	}

		private void SendToBrowser(Byte[] bSendData)
		{
			int numBytes = 0;
			try
			{
				if (mySocket.Connected)
				{
					 numBytes = mySocket.Send(bSendData, bSendData.Length,0);
				}  
						
			}
			catch 
			{ 
				
			}
		}

		public void HandleConnection()
		{
			
			int iStartPos = 0;
			string sRequest,sDirName,  sRequestedFile, sErrorMessage, sLocalDir;
			
			string sPhysicalFilePath = "";
		  	Byte[] bReceive = new Byte[1024] ;
			int i = mySocket.Receive(bReceive,bReceive.Length,0) ;

			//Convert Byte to String
			string sBuffer = Encoding.ASCII.GetString(bReceive);
			
			//At present we will only deal with GET type
			if (sBuffer.Substring(0,3) != "GET" )
			{
				//Form1.WriteToConsole("Only Get Method is supported..\r\n");
				mySocket.Close();
				return;
			}
			
			// Look for HTTP request
			iStartPos = sBuffer.IndexOf("HTTP",1);

			// Get the HTTP text and version e.g. it will return "HTTP/1.1"
			string sHttpVersion = sBuffer.Substring(iStartPos,8);
 					        			
			// Extract the Requested Type and Requested file/directory
			sRequest = sBuffer.Substring(0,iStartPos - 1);

			//Form1.WriteToConsole("File Requested : " +  sRequest + "\r\n");
								
			//Replace backslash with Forward Slash, if Any
			sRequest.Replace("\\","/");

			//If file name is not supplied add forward slash to indicate 
			//that it is a directory and then we will look for the 
			//default file name..
			if ((sRequest.IndexOf(".") <1) && (!sRequest.EndsWith("/")))
			{ 	sRequest = sRequest + "/";  }

			//Extract the requested file name
			iStartPos = sRequest.LastIndexOf("/") + 1;
			sRequestedFile = sRequest.Substring(iStartPos);
			
			//Extract The directory Name
			sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/")-3);
			
			sLocalDir = sMyWebServerRoot;
						
			//If The file name is not supplied then look in the default file list
			if (sRequestedFile.Length == 0 )
			{
				sRequestedFile = "Default.htm";
					if (sRequestedFile == "")
				{
						sErrorMessage = "<H2>Error!! No Default File Name Specified</H2>";
					SendHeader(sHttpVersion,  "", sErrorMessage.Length, " 404 Not Found");
					SendToBrowser ( sErrorMessage);

					mySocket.Close();
					return;
				}
			}
							
			string sMimeType = GetMimeType(sRequestedFile);

			//Build the physical path
			sPhysicalFilePath = sLocalDir + sDirName+ sRequestedFile;
				
			if (File.Exists(sPhysicalFilePath) == false)
			{
				sErrorMessage = "<H2>404 Error! File Does Not Exist...</H2>";
				SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found");
				SendToBrowser(sErrorMessage);

				//Form1.WriteToConsole("File Not found\r\n");
			}
		
			else
			{
				FileStream fs = new FileStream(sPhysicalFilePath, FileMode.Open,FileAccess.Read, FileShare.Read);
				// Create a reader that can read bytes from the FileStream.
				
				BinaryReader reader = new BinaryReader(fs);
					
				byte[] bytes = new byte[fs.Length];
	
				bytes  = reader.ReadBytes((int) fs.Length);
				int totbytes= (int) fs.Length;
					
				reader.Close(); 
				fs.Close();

				SendHeader(sHttpVersion,  sMimeType,totbytes , " 200 OK");
				SendToBrowser(bytes);
			}
			mySocket.Close();						
		}
	}
}


